home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 1997 #2 / Amiga Plus CD - 1997 - No. 02.iso / system / mui / developer / c / examples / dragndrop.c < prev    next >
C/C++ Source or Header  |  1978-06-11  |  11KB  |  434 lines

  1. /*
  2. ** The Settings Demo shows how to load and save object contents.
  3. */
  4.  
  5. #include "mui.h"
  6.  
  7. #include "demo.h"
  8.  
  9. static const char *nase[] =
  10. {
  11.     "Line  1",
  12.     "Line  2",
  13.     "Line  3",
  14.     "Line  4",
  15.     "Line  5",
  16.     "Line  6",
  17.     "Line  7",
  18.     "Line  8",
  19.     "Line  9",
  20.     "Line 10",
  21.     "Line 11",
  22.     "Line 12",
  23.     "Line 13",
  24.     "Line 14",
  25.     "Line 15",
  26.     "Line 16",
  27.     "Line 17",
  28.     "Line 18",
  29.     "Line 19",
  30.     "Line 20",
  31.     "Line 21",
  32.     "Line 22",
  33.     "Line 23",
  34.     "Line 24",
  35.     "Line 25",
  36.     "Line 26",
  37.     "Line 27",
  38.     "Line 28",
  39.     "Line 29",
  40.     "Line 30",
  41.     "Line 31",
  42.     "Line 32",
  43.     "Line 33",
  44.     "Line 34",
  45.     "Line 35",
  46.     "Line 36",
  47.     "Line 37",
  48.     "Line 38",
  49.     "Line 39",
  50.     "Line 40",
  51.     "Line 41",
  52.     "Line 42",
  53.     "Line 43",
  54.     "Line 44",
  55.     "Line 45",
  56.     "Line 46",
  57.     "Line 47",
  58.     "Line 48",
  59.     "Line 49",
  60.     "Line 50",
  61.      NULL,
  62. };
  63.  
  64.  
  65.  
  66. struct MUI_CustomClass *CL_FieldsList;
  67. struct MUI_CustomClass *CL_ChooseFields;
  68.  
  69.  
  70. ULONG __stdargs DoSuperNew(struct IClass *cl,Object *obj,ULONG tag1,...)
  71. {
  72.     return(DoSuperMethod(cl,obj,OM_NEW,&tag1,NULL));
  73. }
  74.  
  75.  
  76.  
  77. /****************************************************************************/
  78. /* FieldsList class                                                         */
  79. /****************************************************************************/
  80.  
  81. /*
  82. ** FieldsList list class creates a list that accepts D&D items
  83. ** from exactly one other listview, the one which is stored in
  84. ** the objects userdata. You could also store the allowed source
  85. ** object in another private attribute, I was just too lazy to add
  86. ** the get/set methods in this case. :-)
  87. **
  88. ** This class is designed to be used for both, the list of the
  89. ** available fields and the list of the visible fields.
  90. **
  91. ** Note: Stop being afraid of custom classes. This one here takes
  92. ** just a few lines of code, 90% of the stuff below is comments. :-)
  93. */
  94.  
  95.  
  96. struct FieldsList_Data
  97. {
  98.     LONG dummy;
  99. };
  100.  
  101.  
  102. ULONG FieldsList_DragQuery(struct IClass *cl,Object *obj,struct MUIP_DragDrop *msg)
  103. {
  104.     if (msg->obj==obj)
  105.     {
  106.         /*
  107.         ** If somebody tried to drag ourselves onto ourselves, we let our superclass
  108.         ** (the list class) handle the necessary actions. Depending on the state of
  109.         ** its MUIA_List_DragSortable attribute, it will either accept or refuse to become
  110.         ** the destination object.
  111.         */
  112.  
  113.         return(DoSuperMethodA(cl,obj,msg));
  114.     }
  115.     else if (msg->obj==(Object *)muiUserData(obj))
  116.     {
  117.         /*
  118.         ** If our predefined source object wants us to become active,
  119.         ** we politely accept it.
  120.         */
  121.  
  122.         return(MUIV_DragQuery_Accept);
  123.     }
  124.     else
  125.     {
  126.         /*
  127.         ** Otherwise, someone tried to feed us with something we don't like
  128.         ** very much. Just refuse it.
  129.         */
  130.  
  131.         return(MUIV_DragQuery_Refuse);
  132.     }
  133.  
  134. }
  135.  
  136.  
  137. ULONG FieldsList_DragDrop(struct IClass *cl,Object *obj,struct MUIP_DragDrop *msg)
  138. {
  139.     if (msg->obj==obj)
  140.     {
  141.         /*
  142.         ** user wants to move entries within our object, these kinds of actions
  143.         ** can get quite complicated, but fortunately, everything is automatically
  144.         ** handled by list class. We just need to pass through the method.
  145.         */
  146.  
  147.         return(DoSuperMethodA(cl,obj,msg));
  148.     }
  149.     else
  150.     {
  151.         /*
  152.         ** we can be sure that msg->obj is our predefined source object
  153.         ** since we wouldnt have accepted the MUIM_DragQuery and wouldnt
  154.         ** have become an active destination object otherwise.
  155.         */
  156.  
  157.         APTR entry;
  158.         LONG dropmark;
  159.         LONG sortable;
  160.  
  161.         /*
  162.         ** get the current entry from the source object, remove it there, and insert
  163.         ** it to ourselves. You would have to do a little more action if the source
  164.         ** listview would support multi select, but this one doesnt, so things get
  165.         ** quite easy. Note that this direct removing/adding of list entries is only
  166.         ** possible if both contain lists simple pointers to static items. If they would
  167.         ** feature custom construct/destruct hooks, we'd need to create a copy of
  168.         ** the entries instead of simply moving pointers.
  169.         */
  170.  
  171.         /* get source entry */
  172.         DoMethod(msg->obj,MUIM_List_GetEntry,MUIV_List_GetEntry_Active,&entry);
  173.  
  174.         /* remove source entry */
  175.         DoMethod(msg->obj,MUIM_List_Remove,MUIV_List_Remove_Active);
  176.  
  177.         get(obj,MUIA_List_DragSortable,&sortable);
  178.         if (sortable)
  179.         {
  180.             /*
  181.             ** if we are in a sortable list (in our case the visible fields),
  182.             ** we need to make sure to insert the new entry at the correct
  183.             ** position. The MUIA_List_DropMark attribute is maintained
  184.             ** by list class and shows us where we shall go after a drop.
  185.             */
  186.  
  187.             get(obj,MUIA_List_DropMark,&dropmark);
  188.             DoMethod(obj,MUIM_List_InsertSingle,entry,dropmark);
  189.         }
  190.         else
  191.         {
  192.             /*
  193.             ** we are about to return something to the available fields
  194.             ** listview which is always sorted.
  195.             */
  196.  
  197.             DoMethod(obj,MUIM_List_InsertSingle,entry,MUIV_List_Insert_Sorted);
  198.         }
  199.  
  200.         /*
  201.         ** make the insterted object the active and make the source listviews
  202.         ** active object inactive to give some more visual feedback to the user.
  203.         */
  204.  
  205.         get(obj,MUIA_List_InsertPosition,&dropmark);
  206.         set(obj,MUIA_List_Active,dropmark);
  207.         set(msg->obj,MUIA_List_Active,MUIV_List_Active_Off);
  208.  
  209.         return(0);
  210.     }
  211. }
  212.  
  213.  
  214. SAVEDS ASM ULONG FieldsList_Dispatcher(REG(a0) struct IClass *cl,REG(a2) Object *obj,REG(a1) Msg msg)
  215. {
  216.     switch (msg->MethodID)
  217.     {
  218.         case MUIM_DragQuery: return(FieldsList_DragQuery(cl,obj,(APTR)msg));
  219.         case MUIM_DragDrop : return(FieldsList_DragDrop (cl,obj,(APTR)msg));
  220.     }
  221.     return(DoSuperMethodA(cl,obj,msg));
  222. }
  223.  
  224.  
  225.  
  226. /****************************************************************************/
  227. /* ChooseFields class                                                       */
  228. /****************************************************************************/
  229.  
  230. /*
  231. ** This class creates two listviews, one contains all available fields,
  232. ** the other one contains the visible fields. You can control this
  233. ** stuff completely with D&D. This thing could e.g. be useful to
  234. ** configure the display of an address utility.
  235. */
  236.  
  237. static const char *fields[] =
  238. {
  239.     "Age",
  240.     "Birthday",
  241.     "c/o",
  242.     "City",
  243.     "Comment",
  244.     "Country",
  245.     "EMail",
  246.     "Fax",
  247.     "First name",
  248.     "Job",
  249.     "Name",
  250.     "Phone",
  251.     "Projects",
  252.     "Salutation",
  253.     "State",
  254.     "Street",
  255.     "ZIP",
  256.     NULL
  257. };
  258.  
  259. struct ChooseFields_Data
  260. {
  261.     LONG dummy;
  262. };
  263.  
  264. ULONG ChooseFields_New(struct IClass *cl,Object *obj,struct opSet *msg)
  265. {
  266.     Object *available, *visible;
  267.  
  268.     obj = (Object *)DoSuperNew(cl,obj,
  269.         MUIA_Group_Columns, 2,
  270.         MUIA_Group_VertSpacing, 1,
  271.         Child, TextObject, MUIA_Text_Contents, "\33cAvailable Fields\n(alpha sorted)", End,
  272.         Child, TextObject, MUIA_Text_Contents, "\33cVisible Fields\n(sortable)", End,
  273.         Child, ListviewObject,
  274.             MUIA_Listview_DragType, 1,
  275.             MUIA_Listview_List, available = NewObject(CL_FieldsList->mcc_Class,NULL,
  276.                 InputListFrame,
  277.                 MUIA_List_SourceArray, (char **)fields,
  278.                 MUIA_List_ShowDropMarks, FALSE,
  279.                 TAG_DONE),
  280.             End,
  281.         Child, ListviewObject,
  282.             MUIA_Listview_DragType, 1,
  283.             MUIA_Listview_List, visible = NewObject(CL_FieldsList->mcc_Class,NULL,
  284.                 InputListFrame,
  285.                 MUIA_List_DragSortable, TRUE,
  286.                 TAG_DONE),
  287.             End,
  288.         End;
  289.  
  290.     if (obj)
  291.     {
  292.         /*
  293.         ** tell available object to accept items from visible object.
  294.         ** the use of MUIA_UserData is just to make the FieldsList
  295.         ** subclass more simple.
  296.         */
  297.  
  298.         set(available,MUIA_UserData,visible);
  299.  
  300.         /*
  301.         ** the other way round...
  302.         */
  303.  
  304.         set(visible,MUIA_UserData,available);
  305.     }
  306.  
  307.     return((ULONG)obj);
  308. }
  309.  
  310. SAVEDS ASM ULONG ChooseFields_Dispatcher(REG(a0) struct IClass *cl,REG(a2) Object *obj,REG(a1) Msg msg)
  311. {
  312.     switch (msg->MethodID)
  313.     {
  314.         case OM_NEW: return(ChooseFields_New(cl,obj,(APTR)msg));
  315.     }
  316.     return(DoSuperMethodA(cl,obj,msg));
  317. }
  318.  
  319.  
  320.  
  321. /****************************************************************************/
  322. /* Main Program                                                             */
  323. /****************************************************************************/
  324.  
  325.  
  326. VOID ExitClasses(VOID)
  327. {
  328.     if (CL_FieldsList  ) MUI_DeleteCustomClass(CL_FieldsList  );
  329.     if (CL_ChooseFields) MUI_DeleteCustomClass(CL_ChooseFields);
  330. }
  331.  
  332.  
  333. BOOL InitClasses(VOID)
  334. {
  335.     CL_FieldsList    = MUI_CreateCustomClass(NULL,MUIC_List ,NULL,sizeof(struct FieldsList_Data),FieldsList_Dispatcher);
  336.     CL_ChooseFields  = MUI_CreateCustomClass(NULL,MUIC_Group,NULL,sizeof(struct ChooseFields_Data ),ChooseFields_Dispatcher );
  337.  
  338.     if (CL_FieldsList && CL_ChooseFields)
  339.         return(TRUE);
  340.  
  341.     ExitClasses();
  342.     return(FALSE);
  343. }
  344.  
  345.  
  346. int main(int argc,char *argv[])
  347. {
  348.     Object *app,*window;
  349.  
  350.     init();
  351.  
  352.     if (!InitClasses())
  353.         fail(NULL,"failed to init classes.");
  354.  
  355.     app = ApplicationObject,
  356.         MUIA_Application_Title      , "DragnDrop",
  357.         MUIA_Application_Version    , "$VER: DragnDrop 17.6 (18.08.96)",
  358.         MUIA_Application_Copyright  , "©1992-95, Stefan Stuntz",
  359.         MUIA_Application_Author     , "Stefan Stuntz",
  360.         MUIA_Application_Description, "Demonstrate Drag & Drop capabilities",
  361.         MUIA_Application_Base       , "DRAGNDROP",
  362.  
  363.         SubWindow, window = WindowObject,
  364.             MUIA_Window_Title, "Drag&Drop Demo",
  365.             MUIA_Window_ID   , MAKE_ID('D','R','A','G'),
  366.             WindowContents, VGroup,
  367.  
  368.                 Child, NewObject(CL_ChooseFields->mcc_Class,NULL,TAG_DONE),
  369.  
  370.                 Child, ColGroup(2),
  371.                     Child, TextObject, TextFrame, MUIA_Background, MUII_TextBack, MUIA_Text_Contents, "\33cListview without\nmultiple selection.", End,
  372.                     Child, TextObject, TextFrame, MUIA_Background, MUII_TextBack, MUIA_Text_Contents, "\33cListview with\nmultiple selection.", End,
  373.                     Child, ListviewObject,
  374.                         MUIA_Listview_DragType, 1,
  375.                         MUIA_Dropable, FALSE,
  376.                         MUIA_Listview_List, ListObject,
  377.                             InputListFrame,
  378.                             MUIA_List_SourceArray, nase,
  379.                             MUIA_List_DragSortable, TRUE,
  380.                             End,
  381.                         End,
  382.                     Child, ListviewObject,
  383.                         MUIA_Dropable, TRUE,
  384.                         MUIA_Listview_DragType, 1,
  385.                         MUIA_Listview_MultiSelect, MUIV_Listview_MultiSelect_Default,
  386.                         MUIA_Listview_List, ListObject,
  387.                             InputListFrame,
  388.                             MUIA_List_SourceArray, nase,
  389.                             MUIA_List_DragSortable, TRUE,
  390.                             End,
  391.                         End,
  392.                     End,
  393.                 End,
  394.             End,
  395.         End;
  396.  
  397.     if (!app)
  398.         fail(app,"Failed to create Application.");
  399.  
  400.  
  401.     DoMethod(window,MUIM_Notify,MUIA_Window_CloseRequest,TRUE,
  402.         app,2,MUIM_Application_ReturnID,MUIV_Application_ReturnID_Quit);
  403.  
  404.  
  405.     /*
  406.     ** This is the ideal input loop for an object oriented MUI application.
  407.     ** Everything is encapsulated in classes, no return ids need to be used,
  408.     ** we just check if the program shall terminate.
  409.     ** Note that MUIM_Application_NewInput expects sigs to contain the result
  410.     ** from Wait() (or 0). This makes the input loop significantly faster.
  411.     */
  412.  
  413.     set(window,MUIA_Window_Open,TRUE);
  414.  
  415.     {
  416.         ULONG sigs = 0;
  417.  
  418.         while (DoMethod(app,MUIM_Application_NewInput,&sigs) != MUIV_Application_ReturnID_Quit)
  419.         {
  420.             if (sigs)
  421.             {
  422.                 sigs = Wait(sigs | SIGBREAKF_CTRL_C);
  423.                 if (sigs & SIGBREAKF_CTRL_C) break;
  424.             }
  425.         }
  426.     }
  427.  
  428.     set(window,MUIA_Window_Open,FALSE);
  429.  
  430.     MUI_DisposeObject(app); /* note that you must first dispose all objects */
  431.     ExitClasses();          /* *before* deleting the classes! */
  432.     fail(NULL,NULL);
  433. }
  434.